﻿using System;
using System.Collections.Generic;
using SlimDX;
using StillDesign;
using Editor.Rendering;
using Editor.Mesh;

namespace Editor
{
    public class Entity
    {
        private List<KeyValuePair<Material, MeshData>> m_Meshes = new List<KeyValuePair<Material, MeshData>>();
        private StillDesign.PhysX.Actor m_Actor;
        private Matrix m_Transform;
        private Entity m_Parent;

        public StillDesign.PhysX.Actor Actor
        {
            get { return m_Actor; }
            set { m_Actor = value; }
        }

        public Matrix LocalTransform
        {
            get { return m_Transform; }
            set { m_Transform = value; m_Actor.GlobalPose = value; }
        }

        public Entity Parent
        {
            get { return m_Parent; }
            set { m_Parent = value; }
        }

        public int HierarchyLevel
        {
            get { return (m_Parent == null) ? 0 : (m_Parent.HierarchyLevel + 1); }
        }

        public Matrix HierarchicalTransform
        {
            get { return (m_Parent == null) ? LocalTransform : (Matrix.Multiply(LocalTransform, m_Parent.HierarchicalTransform)); }
        }

        public void AddMeshInstance(Material material, MeshData mesh)
        {
            m_Meshes.Add(new KeyValuePair<Material, MeshData>(material, mesh));
        }

        public void Move(Vector3 offset)
        {
            Matrix matTranslate = Matrix.Translation(offset);
            Matrix matInvCurr = Matrix.Invert(LocalTransform);

            LocalTransform = Matrix.Multiply(LocalTransform, matTranslate);
        }

        public void Rotate(Quaternion rot)
        {
            Quaternion currRot = Quaternion.RotationMatrix(LocalTransform);
            Quaternion invCurrRot = Quaternion.Invert(currRot);

            Quaternion transform = Quaternion.Multiply(Quaternion.Multiply(invCurrRot, rot), currRot);
            LocalTransform = Matrix.Multiply(Matrix.RotationQuaternion(transform), LocalTransform);
        }

        public void Render(SlimDX.Direct3D9.Device device, Matrix matView, Matrix matProjection)
        {
            Matrix matWorld = HierarchicalTransform;

            foreach (KeyValuePair<Material, MeshData> meshInstance in m_Meshes)
            {
                Material material = meshInstance.Key;
                MeshData mesh = meshInstance.Value;
                material.Render(device, matWorld, matView, matProjection,
                    mesh.VertexBuffer, typeof(MeshData.VertexPositionNormalUV), mesh.Positions.Count,
                    mesh.IndexBuffer, SlimDX.Direct3D9.PrimitiveType.TriangleList, mesh.Indices.Count / 3);
            }
        }
    }
}
